程序终止

  一个程序可能以多种方式终止:

通过从main()返回。
通过调用exit()。
通过调用abort()。
通过抛出一个未被捕捉的异常。

此外,还有各种各样病态的或者依赖于实现的使程序垮台的方式。

  如果一个程序利用标准库函数exit()终止,所有已经构造起来的静态对象的析构函数都将被调用(10.4.9节、10.2.4节)。然而,如果程序使用标准库函数abort()而终止,那么析构函数就不会被调用。请注意,这意味着exit()并不立即终止程序。在析构函数里调用exit()有可能导致无穷递归。exit()的类型是

void exit(int);

和main()的返回值一样(3.2节),exit()的参数也将被作为程序的值返回给“系统”。用零指明程序成功结束。

  调用exit()结束程序,意味着调用它的函数及其调用者里的局部变量的析构函数不会执行。抛出一个异常并捕捉它则能保证局部变量被正确地销毁(14.4.7节)。此外,调用exit()将终止程序,不会给调用exit()函数的调用者留下处理问题的机会。因此,最好是通过抛出异常以脱离一个环境,让异常处理器去决定下面应该做些什么。

  C(和C++)标准库函数atexit()使我们可以让程序在终止前执行一些代码。例如,

    void my_cleanup();

    void somewhere()
    {
        if(atexit(&my_cleanup)==0)
        {
            // 在正常终止时将调用my_cleanup()
        }
        else
        {
            // 呜呼:atexit函数太多
        }
    }

这非常像在程序终止时对全局变量自动调用析构函数(10.4.9节、10.2.4节)。请注意,提供给atexit()的参数函数不能有参数也不能返回值。另外,这里存在着一个由实现确定atexit()函数的最大数目。atexit()通过返回非0值表明已经达到了最大限制。这些约束情况也使atexit()不如它初看起来那么有用。

  在atexit(f)调用之前被静态分配的对象(全局的,10.4.9节;函数static,7.1.2节;或者类static,10.2.4节)的析构函数将在f的调用之后被调用。在一个atexit(f)调用之后建立的这种对象的析构函数将在f的调用之前被调用。

  函数exit()、abort()和atexit()在 <cstdlib> 里声明。

🔚